﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.LogEntries.LogEntryHistory
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using System;
using System.Collections.Generic;
using TaleWorlds.Library;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem.LogEntries
{
  public class LogEntryHistory
  {
    [SaveableField(0)]
    internal long LastAddedIndex = -1;
    [SaveableField(1)]
    private readonly MBList<LogEntry> _logs = new MBList<LogEntry>();

    internal static void AutoGeneratedStaticCollectObjectsLogEntryHistory(
      object o,
      List<object> collectedObjects)
    {
      ((LogEntryHistory) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
    }

    protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
    {
      collectedObjects.Add((object) this._logs);
    }

    internal static object AutoGeneratedGetMemberValueLastAddedIndex(object o)
    {
      return (object) ((LogEntryHistory) o).LastAddedIndex;
    }

    internal static object AutoGeneratedGetMemberValue_logs(object o)
    {
      return (object) ((LogEntryHistory) o)._logs;
    }

    internal void AddActionLog(LogEntry actionLog, bool checkSequenceAndInsert = false)
    {
      if (this._logs.Count > 0 && this._logs[this._logs.Count - 1].Id > actionLog.Id)
      {
        Debug.FailedAssert("Log ids should always get bigger", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\LogEntries\\LogEntry.cs", nameof (AddActionLog), 209);
        int index = this._logs.FindIndex((Predicate<LogEntry>) (l => l.Id > actionLog.Id));
        if (index >= 0)
          this._logs.Insert(index, actionLog);
      }
      else
        this._logs.Add(actionLog);
      Campaign.Current.CampaignInformationManager.NewLogEntryAdded(actionLog);
    }

    internal void DeleteLogAtIndex(int i) => this._logs.RemoveAt(i);

    public void DeleteOutdatedLogs()
    {
      int index1 = -1;
      for (int index2 = 0; index2 < this._logs.Count; ++index2)
      {
        LogEntry log = this._logs[index2];
        if (!(log.KeepInHistoryTime + log.GameTime).IsPast)
        {
          ++index1;
          if (index2 != index1)
            this._logs[index1] = log;
        }
      }
      if (index1 >= this._logs.Count)
        return;
      this._logs.RemoveRange(index1 + 1, this._logs.Count - index1 - 1);
    }

    public MBReadOnlyList<LogEntry> GameActionLogs => (MBReadOnlyList<LogEntry>) this._logs;

    public IEnumerable<T> GetGameActionLogs<T>(Func<T, bool> predicate) where T : LogEntry
    {
      foreach (LogEntry log in (List<LogEntry>) this._logs)
      {
        if (log is T gameActionLog && predicate(gameActionLog))
          yield return gameActionLog;
      }
    }

    public T FindLastGameActionLog<T>(Func<T, bool> predicate) where T : LogEntry
    {
      for (int index = this._logs.Count - 1; index >= 0; --index)
      {
        if (this._logs[index] is T log && predicate(log))
          return log;
      }
      return default (T);
    }

    private int BinarySearchFirst(long target)
    {
      int num1 = 0;
      int num2 = this._logs.Count - 1;
      while (num1 < num2)
      {
        int index = (num1 + num2 + 1) / 2;
        if (this._logs[index].Id > target)
          num2 = index - 1;
        else
          num1 = index;
      }
      return num2;
    }

    private int BinarySearchFirst(CampaignTime target)
    {
      int num1 = 0;
      int num2 = this._logs.Count - 1;
      while (num1 < num2)
      {
        int index = (num1 + num2 + 1) / 2;
        if (this._logs[index].GameTime > target)
          num2 = index - 1;
        else
          num1 = index;
      }
      return num2;
    }

    public int GetStartIndexForComments()
    {
      for (int index = MathF.Max(0, this._logs.Count - 10000); index < this._logs.Count; ++index)
      {
        if (this._logs[index].Id > Hero.OneToOneConversationHero.LastExaminedLogEntryID)
          return index;
      }
      return this._logs.Count;
    }

    public LogEntry GetRelevantComment(
      Hero conversationHero,
      out int bestScore,
      out string bestRelatedLogEntryTag)
    {
      int index1 = -1;
      bestRelatedLogEntryTag = "";
      int indexForComments = this.GetStartIndexForComments();
      bestScore = 0;
      if (indexForComments < this._logs.Count)
      {
        for (int index2 = indexForComments; index2 < this._logs.Count; ++index2)
        {
          ImportanceEnum score;
          this._logs[index2].GetConversationScoreAndComment(conversationHero, false, out string _, out score);
          int num = (int) score;
          if (num > bestScore)
          {
            bestScore = num;
            index1 = index2;
          }
        }
        Hero.OneToOneConversationHero.LastExaminedLogEntryID = this._logs[this._logs.Count - 1].Id;
      }
      if (index1 <= -1)
        return (LogEntry) null;
      string comment;
      this._logs[index1].GetConversationScoreAndComment(conversationHero, true, out comment, out ImportanceEnum _);
      bestRelatedLogEntryTag = comment;
      return this._logs[index1];
    }

    internal void OnAfterLoad()
    {
      for (int index = this._logs.Count - 1; index >= 0; --index)
      {
        if (this._logs[index] == null)
          this._logs.RemoveAt(index);
      }
    }
  }
}
